package com.luoguijia.disk.files.service;

import com.luoguijia.disk.files.entity.FileEntity;
import com.luoguijia.disk.files.exception.FileOperationException;
import com.luoguijia.disk.files.repository.FileDao;
import com.luoguijia.disk.mybatis.entity.PtFileEntity;
import com.luoguijia.disk.mybatis.flexigrid.TblResponseEntity;
import com.obs.services.ObsClient;
import com.obs.services.model.ObjectListing;
import com.obs.services.model.ObsObject;
import com.obs.services.model.TemporarySignatureRequest;
import com.obs.services.model.TemporarySignatureResponse;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
public class FileIoServiceImpl implements FileIoService {

    @Value("${end.point}")
    private String endpoint = "";
    @Value("${ak}")
    private String ak = "";
    @Value("${sk}")
    private String sk = "";
    @Value("${bucket.name}")
    private String bucketName = "";

    private ObsClient obsClient = null;

    @Resource
    private FileService fileService;

    @Resource
    private FileDao fileDao;

    private ObsClient getObsClient() {
        if (this.obsClient == null) {
            this.obsClient = new ObsClient(ak, sk, endpoint);
        }
        return this.obsClient;
    }

    private Logger logger = LogManager.getLogger(this.getClass());

    @Override
    public void syncFileData() {
        ObjectListing list = getObsClient().listObjects(bucketName);
        List<ObsObject> listObjects = list.getObjects();
        PtFileEntity ptFileEntity = null;
        List<PtFileEntity> ptFileEntityList = new ArrayList<>();

        List<PtFileEntity> ptFileEntityList1 = fileService.queryFileListAll();
        String uuid = "";

        for (ObsObject obsObject : listObjects) {
            ptFileEntity = new PtFileEntity();
            ptFileEntityList.add(ptFileEntity);
            ptFileEntity.setParentUuid("-1");
            ptFileEntity.setFilePath(obsObject.getObjectKey());
            uuid = UUID.randomUUID().toString();

            for (PtFileEntity ptFileEntityItem : ptFileEntityList1) {
                if (obsObject.getObjectKey().equals(ptFileEntityItem.getFilePath())) {
                    uuid = ptFileEntityItem.getFileUuid();
                    break;
                }
            }

            ptFileEntity.setFileUuid(uuid);
            ptFileEntity.setFileCapacity(obsObject.getMetadata().getContentLength());
            logger.info("obsClient obsKey:" + obsObject.getObjectKey()
                    + "  obsClient obsSize:" + obsObject.getMetadata().getContentLength()
                    + "  obsClient idFolder:" + isFolder(obsObject.getObjectKey()));
            /**
             * 判断是否为文件夹
             */
            if (isFolder(obsObject.getObjectKey())) {
                ptFileEntity.setFileType(FILE_TYPE_FOLDER);
            } else {
                ptFileEntity.setFileType(FILE_TYPE_FILE);
            }
            /**
             * 获取文件名称
             */
            ptFileEntity.setFileName(getFileName(obsObject.getObjectKey()));

//            logger.info(ptFileEntity);

        }

        for (PtFileEntity child : ptFileEntityList) {
            for (PtFileEntity parent : ptFileEntityList) {
                if (child.getFilePath().equals(parent.getFilePath())) {
                    continue;
                }


                //如果父亲是文件跳过
                if (FILE_TYPE_FILE == parent.getFileType()) {
                    continue;
                }

                //文件路径中包含父亲节点路径
                if (child.getFilePath().indexOf(parent.getFilePath()) != -1) {
                    child.setParentUuid(parent.getFileUuid());
                }
            }
        }

        logger.info(ptFileEntityList);
        fileService.saveFileInfo(ptFileEntityList);


    }

    @Override
    public ResponseEntity<byte[]> downFile(String fileUuid) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        if(entity== null){
            return null;
        }
        HttpHeaders headers = new HttpHeaders();
        headers.setContentDispositionFormData("attachment",
                entity.getFileName());
        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        ObsObject obsObject = getObsClient().getObject(bucketName, entity.getFilePath());
        InputStream inputStream = obsObject.getObjectContent();
        byte[] block = new byte[1024];
        int length = 0;

        byte[] fileByte = new byte[0];
        try (
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ){
            while ((length = inputStream.read(block)) > 0){
                byteArrayOutputStream.write(block,0,length);
                byteArrayOutputStream.flush();
            }
            fileByte = byteArrayOutputStream.toByteArray();

        }catch (IOException e){
            logger.info(e);
        }
        return new ResponseEntity<>(
                fileByte,
                headers,
                HttpStatus.CREATED
        );
    }

    @Override
    public void uploadFile(String parentId, String fileName, InputStream inputStream) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileNameU = fileName;
        if (entity != null) {
            fileNameU = entity.getFilePath() + fileName;
        }
        getObsClient().putObject(bucketName, fileNameU, inputStream);
        syncFileData();
    }

    @Override
    public String getShareUrl(String fileUuid) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(entity.getFilePath());
        request.setRequestDate(new Date());
        request.setExpires(60*60);
        TemporarySignatureResponse signature = getObsClient().createTemporarySignature(request);
        String url = signature.getSignedUrl();

        return url;
    }

    @Override
    public String queryShareUrl(String fileUuid, Integer fileValidity) {
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(entity.getFilePath());
        request.setRequestDate(new Date());
        request.setExpires(60*60*24*fileValidity);
        TemporarySignatureResponse signature = getObsClient().createTemporarySignature(request);
        String url = signature.getSignedUrl();

        return url;
    }

    @Override
    public void copyFile(String parentId, String srcUuidList) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String folder = "";
        ObsObject obsObject;
        InputStream inputStream;
        if (entity != null) {
            folder = entity.getFilePath();
        }
        String[] fileUuidArray = srcUuidList.split(",");
        String filePath = "";
        for (String fileUuid : fileUuidArray) {
            entity = fileService.queryFileInfoById(fileUuid);
            if (entity != null) {
                filePath = folder + entity.getFileName();
                /**
                 * 判断是否文件夹
                 */
                if (FILE_TYPE_FOLDER.equals(entity.getFileType())) {
                    getObsClient().putObject(bucketName, filePath, new ByteArrayInputStream(new byte[0]));
                } else {
                    obsObject = getObsClient().getObject(bucketName, entity.getFilePath());
                    inputStream = obsObject.getObjectContent();
                    getObsClient().putObject(bucketName, filePath, inputStream);
                }
            }
        }

        syncFileData();
    }





    /**
     * 是否为文件夹
     *
     * @param filePath
     * @return
     */
    private boolean isFolder(String filePath) {
        boolean rstB = false;
        if (filePath.length() > 0) {
            String lastStr = filePath.substring(filePath.length() - 1);
            if ("springBoot/".equals(filePath)) {
                String aaa = "bbb";
            }
            if (FILE_SEPARATOR.equals(lastStr)) {
                return true;
            }
        }
        return rstB;
    }

    /**
     * 获取文件名称
     *
     * @param filePath
     * @return
     */
    private String getFileName(String filePath) {
        String fileName = filePath;
        if (filePath.indexOf(FILE_SEPARATOR) != -1) {
            String[] fileArray = filePath.split(FILE_SEPARATOR);
            if (isFolder(filePath)) {
                fileName = fileArray[fileArray.length - 1] + FILE_SEPARATOR;
            } else {
                fileName = fileArray[fileArray.length - 1];
            }
        }

        return fileName;
    }


    @Override
    public TblResponseEntity<String> renameFile(FileDao renameDTO, String userId) throws FileOperationException {
        return null;
    }

    // 创建文件夹
    @Override
    public void mkdirFileInfo(String parentId, String folderName) {
        PtFileEntity entity = fileService.queryFileInfoById(parentId);
        String fileName = folderName;
        if (entity != null) {
            fileName = entity.getFilePath() + FILE_SEPARATOR + folderName;
        }
        fileName = fileName + FILE_SEPARATOR;
        getObsClient().putObject(bucketName, fileName, new ByteArrayInputStream(new byte[0]));
        syncFileData();
    }

    // 音视频在线预览
    @Override
    public String getPreviewUrl(String fileUuid) {
        // 预览链接与分享链接逻辑相同，但有效期可以更短
        PtFileEntity entity = fileService.queryFileInfoById(fileUuid);
        TemporarySignatureRequest request = new TemporarySignatureRequest();
        request.setBucketName(bucketName);
        request.setObjectKey(entity.getFilePath());
        request.setRequestDate(new Date());
        // 预览链接设置2小时有效期
        request.setExpires(60 * 120);
        TemporarySignatureResponse signature = getObsClient().createTemporarySignature(request);
        return signature.getSignedUrl();
    }
}



